package com.spring.security.model;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.SpringContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.util.ObjectUtils;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.LinkedHashMap;

/**
 * @author HouKunLin
 */
@Slf4j
public class JsonResult extends LinkedHashMap<Object, Object> {
    private static ObjectMapper objectMapper;

    private boolean dataIsObject = false;

    private static final String DATA_KEY = "data";

    static {
        objectMapper = SpringContext.getBean(ObjectMapper.class);
    }

    public JsonResult() {
        this(0, "success");
    }

    public JsonResult(String msg) {
        this(0, msg);
    }

    public JsonResult(int code, String msg) {
        put("code", code);
        put("msg", msg);
        put("timestamp", new Date());
    }

    public JsonResult(HttpStatus status, String msg) {
        this(status.value(), msg);
        put("reasonPhrase", status.getReasonPhrase());
    }

    private JsonResult(boolean isPrivate) {
    }

    public boolean isOk() {
        return ObjectUtils.nullSafeEquals(0, get("code"));
    }

    @Override
    @NotNull
    public JsonResult put(Object key, Object value) {
        if (!DATA_KEY.equals(key)) {
            super.put(key, value);
        } else {
            data(value);
        }
        return this;
    }

    public JsonResult data(Object data) {
        if (!(data instanceof JsonResultDataMap)) {
            dataIsObject = true;
        }
        super.put(DATA_KEY, data);
        return this;
    }

    public JsonResultDataMap data() {
        if (dataIsObject) {
            throw new RuntimeException("当前的data数据类型不是JsonResultDataMap对象");
        }
        Object data = get(DATA_KEY);
        JsonResultDataMap map;
        if (data == null) {
            map = new JsonResultDataMap();
        } else if (data instanceof JsonResultDataMap) {
            map = (JsonResultDataMap) data;
        } else {
            throw new RuntimeException("当前的data数据类型不是JsonResultDataMap对象");
        }
        super.put(DATA_KEY, map);
        return map;
    }

    public String toJSONString() {
        try {
            String json = objectMapper.writeValueAsString(this);
            log.debug(json);
            return json;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return super.toString();
        }
    }

    public static JsonResult ok() {
        return new JsonResult();
    }

    public static JsonResult ok(String msg) {
        return new JsonResult(msg);
    }

    public static JsonResult ok(Object data) {
        return new JsonResult().data(data);
    }

    public static JsonResult ok(String msg, Object data) {
        return new JsonResult(msg).data(data);
    }

    public static JsonResult error() {
        return new JsonResult(1, "unknown error");
    }

    public static JsonResult error(String msg) {
        return new JsonResult(1, msg);
    }

    public static JsonResult status(HttpStatus status, String msg) {
        return new JsonResult(status, msg);
    }

    public static JsonResult error(Exception e) {
        return new JsonResult(1, e.getMessage());
    }

    public static JsonResult error(HttpStatus status, Exception e) {
        return new JsonResult(status, e.getMessage());
    }

    public class JsonResultDataMap extends LinkedHashMap<Object, Object> {
        @Override
        @NotNull
        public JsonResultDataMap put(Object key, Object value) {
            super.put(key, value);
            return this;
        }

        public boolean isOk() {
            return JsonResult.this.isOk();
        }

        public JsonResult result() {
            return JsonResult.this;
        }
    }

}
